﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
using Validation.sp2010.Classes;
using System.Collections.Generic;
using Validation.sp2010.Helper;
using System.Globalization;
using Microsoft.SharePoint.Utilities;
using System.Collections.Specialized;
using System.Net;
using System.Net.Mail;

namespace Validation.sp2010.WorkFlow.ValidationWorkflow
{
    public sealed partial class ValidationWorkflow : SequentialWorkflowActivity
    {
        public ValidationWorkflow()
        {
            InitializeComponent();
        }
        #region messages

        string label_step_task;
        string label_step_mail;
        string label_step_extension;
        string msg_mail;
        string msg_validate;
        string msg_refuse;
        string msg_extension;
        string msg_loging_format;
        string msg_no_comment;
        string msg_hsitoric_item_format;
        #endregion

        #region Properties
        List<StepWF> steps;
        ValidationWorkflowAssociation parametres;
        bool workFlowTerminated = false;
        bool useStep = true;
        int currentStep = 0;
        string nextValidator;
        string taskCompletedValue;
        bool approuved = false;

        string commentHistoricItem = string.Empty;
        string actorHistoricitem = string.Empty;
        string logError = "";
        #endregion
        public Guid workflowId = default(System.Guid);
        public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();

        private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
        {
            #region Set messages

            SPWeb web = workflowProperties.Web;
            label_step_task = HelperUtilities.GetResources("label_step_task", web.Language);
            label_step_mail = HelperUtilities.GetResources("label_step_mail", web.Language);
            label_step_extension = HelperUtilities.GetResources("label_step_extension", web.Language);
            msg_mail = HelperUtilities.GetResources("msg_mail", web.Language);
            msg_validate = HelperUtilities.GetResources("msg_validate", web.Language);
            msg_refuse = HelperUtilities.GetResources("msg_refuse", web.Language);
            msg_extension = HelperUtilities.GetResources("msg_extension", web.Language);
            msg_loging_format = HelperUtilities.GetResources("msg_loging_format", web.Language);
            msg_no_comment = HelperUtilities.GetResources("msg_no_comment", web.Language);
            msg_hsitoric_item_format = HelperUtilities.GetResources("msg_hsitoric_item_format", web.Language);
            taskCompletedValue = SPResource.GetString(CultureInfo.GetCultureInfo((int)workflowProperties.Web.Language), "WorkflowTaskStatusComplete");

            #endregion

            parametres = Helper.HelperSerializer.XmlDeserializeFromString(workflowProperties.AssociationData, typeof(ValidationWorkflowAssociation)) as ValidationWorkflowAssociation;
            steps = parametres.Steps;

            //set item state to in progress
            try
            {
                SPList list = workflowProperties.List;
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.StateFieldId)] = (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[1];
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "onWorkflowActivated1_Invoked :" + ex.Message;
            }

        }

        #region While boucle
        private void TerminateStepsCondition(object sender, ConditionalEventArgs e)
        {
            e.Result = !workFlowTerminated;
        }

        #region ifElseTask
        private void IsTaskCondition(object sender, ConditionalEventArgs e)
        {
            //we use extension task or our step is  task validation
            e.Result = !useStep || (this.steps[currentStep].TypeStep == TypeStep.Task);
        }

        #region Create Task
        public Guid CreateTask_TaskId = default(System.Guid);
        public SPWorkflowTaskProperties CreateTask_TaskProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public String CreateTask_ContentTypeId = default(System.String);

        private void CreateTask_MethodInvoking(object sender, EventArgs e)
        {
            CreateTask_TaskId = Guid.NewGuid();
            CreateTask_ContentTypeId = Constante.ct_Task_Validation;
            taskTerminated = false;

            StepWF step = steps[currentStep];
            CreateTask_TaskProperties.Title = HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Object);
            CreateTask_TaskProperties.Description = HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Body);


            if (useStep)
            {

                List<SPPrincipal> usersActor = step.Actor.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);

                if (usersActor.Count > 0 && usersActor[0] != null)
                    CreateTask_TaskProperties.AssignedTo = usersActor[0].LoginName; //fieldUsers.ToString();
                else
                    CreateTask_TaskProperties.AssignedTo = step.Actor.SecondaryValidator;

                CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.WithExtention] = step.WithExtension;

            }
            else
            {
                CreateTask_TaskProperties.AssignedTo = nextValidator;
                CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.WithExtention] = false;

                useStep = true;
            }
            CreateTask_TaskProperties.ExtendedProperties[Constante.FieldGuid.ForceValidation] = step.ForceValidation;
        }

        public SPWorkflowTaskProperties onTaskChanged_AfterProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
        public SPWorkflowTaskProperties onTaskChanged_BeforeProperties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();


        private void onTaskChanged_Invoked(object sender, ExternalDataEventArgs e)
        {
           


            if (onTaskChanged_AfterProperties.ExtendedProperties[SPBuiltInFieldId.TaskStatus]==null ||
                onTaskChanged_AfterProperties.ExtendedProperties[SPBuiltInFieldId.TaskStatus].ToString() != taskCompletedValue)
                return;

            taskTerminated = true;

            SPListItem item = workflowProperties.Item;
            SPList list = workflowProperties.List;
            StepWF step = steps[currentStep];

            SPListItem currentTask = workflowProperties.TaskList.GetItemById(onTaskChanged_AfterProperties.TaskItemId);
            actorHistoricitem = HelperUtilities.GetValueLookup(currentTask[SPBuiltInFieldId.Editor].ToString());
            commentHistoricItem = currentTask[Constante.FieldGuid.Comment] != null ? currentTask[Constante.FieldGuid.Comment].ToString() : string.Empty;
            if (string.IsNullOrEmpty(commentHistoricItem))
                commentHistoricItem = msg_no_comment;

            
            ///Get response
            string _extResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[0];
            string _validatResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[1];
            string _refuseResponse = (workflowProperties.TaskList.Fields[Constante.FieldGuid.Response] as SPFieldChoice).Choices[2];

            string response = onTaskChanged_AfterProperties.ExtendedProperties[Constante.FieldGuid.Response].ToString();

            #region Extension
            if (response == _extResponse)
            {
                useStep = false;
                SPUser nextValidatorUser = workflowProperties.Web.AllUsers[onTaskChanged_AfterProperties.ExtendedProperties[Constante.FieldGuid.NextValidator].ToString()];
                nextValidator = nextValidatorUser.LoginName;

                //Notification
                logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                logToHistory_HistoryOutcome = string.Format(msg_extension, actorHistoricitem, nextValidatorUser.Name, commentHistoricItem);
            }


            #endregion

            #region refuse
            if (response == _refuseResponse)
            {
                workFlowTerminated = true;
                approuved = false;

                //Notification
                logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                logToHistory_HistoryOutcome = string.Format(msg_refuse, actorHistoricitem, commentHistoricItem);
            }
            #endregion

            #region Validated
            if (response == _validatResponse)
            {

                currentStep++;
                if (currentStep == steps.Count)
                {
                    approuved = true;
                    workFlowTerminated = true;
                }

                //Notification
                logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_task, step.Title);
                logToHistory_HistoryOutcome = string.Format(msg_validate, actorHistoricitem, commentHistoricItem);

            }
            #endregion



        }
        bool taskTerminated = false;
        private void TaskTerminatedCondition(object sender, ConditionalEventArgs e)
        {
            e.Result = !taskTerminated;
        }
        #endregion

        #region Update historic Item
        private void UpdateItemistorie_ExecuteCode(object sender, EventArgs e)
        {
            //set historic item
            try
            {
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.HistoriqueFieldId)] += string.Format(msg_hsitoric_item_format, actorHistoricitem, commentHistoricItem);
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "UpdateItemistorie_ExecuteCode :" + ex.Message+"\n\t";
            }
        }
        #endregion






        #region SendMail

        public String SendEmail_Body = default(System.String);
        public String SendEmail_From = default(System.String);
        public StringDictionary SendEmail_Headers = new StringDictionary();
        public String SendEmail_Subject = default(System.String);
        public String SendEmail_To = default(System.String);
        public String SendEmail_CC = default(System.String);

        private void SendMailActivity_ExecuteCode(object sender, EventArgs e)
        {
            StepWF step = steps[currentStep];
            List<SPPrincipal> usersActor = step.Actor.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);
            
            StringDictionary headers = new StringDictionary();
            
            string toMail="";
            usersActor.ForEach(p=>{
            SPUser u=workflowProperties.Web.EnsureUser(p.LoginName);
                if(!string.IsNullOrEmpty(u.Email))
                    toMail+=u.Email+";";
            });
            if(toMail.Length>1)
            toMail= toMail.Remove(toMail.Length - 1);

            string ccMail="";
            if(step.CC_Mail!=null)
            {

            List<SPPrincipal> usersCCMail = step.CC_Mail.GetPrincipal(workflowProperties.Web, workflowProperties.List, workflowProperties.Item);
             usersCCMail.ForEach(p=>{
            SPUser u=workflowProperties.Web.EnsureUser(p.LoginName);
                if(!string.IsNullOrEmpty(u.Email))
                    ccMail+=u.Email+";";
            });

             if (ccMail.Length > 1)
                 ccMail = ccMail.Remove(ccMail.Length - 1);

            }

            try
            {
                sendMail(toMail, ccMail,
                       HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Object),
                       HelperParser.GetFinalStringFromList(workflowProperties.List, workflowProperties.Item, step.Body));


            }
            catch (Exception ex)
            {
                logError += "SendMailActivity_ExecuteCode :" + ex.Message + "\n\t";
            }
            
            currentStep++;
            if (currentStep == steps.Count)
            {
                approuved = true;
                workFlowTerminated = true;
            }

            //Notification
            logToHistory_HistoryDescription = string.Format(msg_loging_format, label_step_mail, step.Title);
            logToHistory_HistoryOutcome = string.Format(msg_mail,string.IsNullOrEmpty(toMail)?"-": toMail,
                string.IsNullOrEmpty(ccMail) ? "-" : ccMail);


        }
        private void sendMail(string to, string cc, string objectMail, string bodyMail)
        {
            if (!string.IsNullOrEmpty(to))
            {
                StringDictionary headers = new StringDictionary();
                headers.Add("to", to);

                if (!string.IsNullOrEmpty(cc))
                    headers.Add("cc", cc);

                headers.Add("bcc", "");
                headers.Add("from", "");
                headers.Add("subject", objectMail);
                headers.Add("content-type", "text/html");
                SPUtility.SendEmail(workflowProperties.Web, headers, bodyMail);
            }

     
        }
        #endregion



        #endregion

        #region Log To Historie

        public String logToHistory_HistoryDescription = default(System.String);
        public String logToHistory_HistoryOutcome = default(System.String);
        private void logToHistory_MethodInvoking(object sender, EventArgs e)
        {

        }

        #endregion





        #endregion

        #region Change state

        private void ChangeState_ExecuteCode(object sender, EventArgs e)
        {
            //set historic item
            try
            {
                SPList list = workflowProperties.List;
                SPListItem item = workflowProperties.Item;
                item[new Guid(parametres.StateFieldId)] = approuved ? (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[2] : (list.Fields[new Guid(parametres.StateFieldId)] as SPFieldChoice).Choices[3];
                item.Update();
            }
            catch (Exception ex)
            {
                logError += "UpdateItemistorie_ExecuteCode :" + ex.Message;
            }
        }
        #endregion











    }
}
